<?php
if(!defined('BASEPATH')) exit('No direct script access allowed');
/* 
	企业微信class
*/
require_once(APPCOMMON.'libraries/Http.php');

class Wework{
	
	protected $url_api_host = 'https://qyapi.weixin.qq.com/cgi-bin/';
	protected $url_accesstoken = 'gettoken';
	protected $url_apidomainip = 'get_api_domain_ip';
	
	protected $url_getuserinfo = 'user/getuserinfo';
	protected $url_user_get = 'user/get';
	protected $url_convert_to_openid = 'user/convert_to_openid';
	protected $url_convert_to_userid = 'user/convert_to_userid';
	
	protected $url_department_list = 'department/list';
	
	protected $url_media_upload = 'media/upload';
	
	protected $url_oauth2_authorize = 'https://open.weixin.qq.com/connect/oauth2/authorize';
	
	protected $corpid;
	protected $corpsecret;
	
	public $access_token;
	
	// 缓存
	public $cache_path;
	
	private $acstoken_cachename;
	
	public $error;
	
	protected $_config;
	
	public function __construct($option = array()){
		$CI = &get_instance();
		$confname = isset($option['confname']) ? $option['confname'] : 'wework';
		$CI->load->config($confname, true);
		$config = $CI->config->item($confname);
		if($option){
			foreach($option as $key => $value){
				$config[$key] = $value;
			}
		}
		if(!$config['corpid']){
			exit('corpid cannot empty');
		}
		$this->_config = $config;
		$this->corpid = $config['corpid'];
		$this->corpsecret = $config['corpsecret'];
		$this->cache_path = APPCOMMON.'cache/wework/';
		$this->acstoken_cachename = 'accessToken_'.$this->corpsecret;
	}
	
	// 获取登录凭证access_token
	public function get_accesstoken(){
		$res = $this->get_cache($this->acstoken_cachename);
		if($res){
			$this->access_token = $res;
			$rs = Http::request($this->url_api_host.$this->url_apidomainip.'?access_token='.$res);
			$rs = json_decode($rs, true);
			if($rs && !$rs['errcode']){
				return $res;
			}
		}
		$req = Http::request($this->url_api_host.$this->url_accesstoken, [
			'corpid' => $this->corpid,
			'corpsecret' => $this->corpsecret
		]);
		if(!$req){
			return false;
		}
		$result = json_decode($req, true);
		if(!$result || $result['errcode']){
			$this->error = $result;
			return false;
		}
		$this->access_token = $result['access_token'];
		$this->set_cache($this->acstoken_cachename, $this->access_token, $result['expires_in'] - 100);
		return $this->access_token;
	}
	
	// 构造网页授权链接获取code
	public function oauth2_redirect($redirect = '', $scope = 'snsapi_base', $state = 'state'){
		$url = $redirect ? $redirect : $this->get_current_url();
		return $this->url_oauth2_authorize.'?appid='.$this->corpid.'&redirect_uri='.urlencode($url).'&response_type=code&scope='.$scope.'&state='.$state.'#wechat_redirect';
	}
	
	// 获取访问用户身份
	// 该接口用于根据code获取成员信息
	public function get_userinfo_bycode($code = '', $access_token = ''){
		if(!$code && !isset($_GET['code'])){
			$url = $this->oauth2_redirect();
			header("Location: $url");
			return false;
		}
		if(!$code){
			$code = htmlspecialchars($_GET['code']);
		}
		$req = Http::request($this->url_api_host.$this->url_getuserinfo, [
			'access_token' => ($access_token ? $access_token : $this->get_accesstoken()),
			'code' => $code
		]);
		if(!$req){
			return false;
		}
		$result = json_decode($req, true);
		if(!$result || $result['errcode']){
			$this->error = $result;
			return false;
		}
		return $result;
	}
	
	// 读取成员
	public function user_get($userid){
		if(!$userid || (!$this->access_token && !$this->get_accesstoken())){
			return false;
		}
		$req = Http::request($this->url_api_host.$this->url_user_get, [
			'access_token' => $this->access_token,
			'userid' => $userid
		]);
		if(!$req){
			return false;
		}
		$result = json_decode($req, true);
		if(!$result || $result['errcode']){
			$this->error = $result;
			return false;
		}
		return $result;
	}
	
	// userid转openid
	public function userid_to_openid($id){
		if(!$id || (!$this->access_token && !$this->get_accesstoken())){
			return false;
		}
		$req = Http::request($this->url_api_host . $this->url_convert_to_openid . '?access_token=' . $this->access_token, json_encode([
			'userid' => $id
		]), 'POST');
		if(!$req){
			return false;
		}
		$result = json_decode($req, true);
		if(!$result || $result['errcode']){
			$this->error = $result;
			return false;
		}
		return $result;
	}
	
	// openid转userid
	public function openid_to_userid($id){
		if(!$id || (!$this->access_token && !$this->get_accesstoken())){
			return false;
		}
		$req = Http::request($this->url_api_host . $this->url_convert_to_userid . '?access_token=' . $this->access_token, json_encode([
			'openid' => $id
		]), 'POST');
		if(!$req){
			return false;
		}
		$result = json_decode($req, true);
		if(!$result || $result['errcode']){
			$this->error = $result;
			return false;
		}
		return $result;
	}
	
	// $id 部门id。获取指定部门及其下的子部门。 
	// 如果不填，默认获取全量组织架构
	public function department_list($id = ''){
		if(!$this->access_token && !$this->get_accesstoken()){
			return false;
		}
		$req = Http::request($this->url_api_host.$this->url_department_list, [
			'access_token' => $this->access_token,
			'id' => $id
		]);
		if(!$req){
			return false;
		}
		$result = json_decode($req, true);
		if(!$result || $result['errcode']){
			$this->error = $result;
			return false;
		}
		return $result;
	}
	
	// 上传临时素材
	# type	媒体文件类型，分别有图片（image）、语音（voice）、视频（video），普通文件（file）
	public function upload_media($type, $params){
		if(!$this->access_token && !$this->get_accesstoken()){
			return false;
		}
		$data = array(
			'curl_upload' => 1,
			'media' => '@'.$params['file']
		);
		$req = Http::request($this->url_api_host.$this->url_media_upload.'?access_token='.$this->access_token.'&type='.$type, $data, 'POST');
		if(!$req){
			return false;
		}
		$result = json_decode($req, true);
		if(!$result || $result['errcode']){
			$this->error = $result;
			return false;
		}
		return $result;
	}
	
	public function get_cache($name){
		$file = $this->cache_path.$name;
		if(!is_file($file)){
			return false;
		}
		$res = json_decode(file_get_contents($file), true);
		if($res['expire'] > 0 && $res['expire'] < time()){
			$this->remove_cache($name);
			return false;
		}
		return $res['data'];
	}
	
	public function set_cache($name, $value, $expire){
		if(!is_dir($this->cache_path)){
			mkdir($this->cache_path, 0775, true);
		}
		$file = $this->cache_path.$name;
		if(!is_file($file)){
			file_put_contents($file, '');
			chmod($file, 0775);
		}
		$content = array(
			'expire' => time() + $expire,
			'data' => $value
		);
		$fp = fopen($file, 'w');
		fwrite($fp, json_encode($content));
		fclose($fp);
	}
	
	public function remove_cache($name){
		unlink($this->cache_path.$name);
	}
	
	public function get_current_url(){
		$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https://' : 'http://';
		return "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
	}
	
	// 随机字符串
	public function rand_str($length = 16){
		$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
		$str = '';
		for ($i = 0; $i < $length; $i++) {
			$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
		}
		return $str;
	}
	
	// 生成唯一id
	public function unique_id(){
		return date('Ymd').sprintf('%05d', date('G')*3600 + date('i')*60 + date('s')).substr(microtime(), 2, 5).sprintf('%02d', rand(0, 99));
	}
	
	public function array_to_xml($arr){
		$xml = '<xml>';
		$xml .= $this->xml_body($arr);
		$xml .= '</xml>';
		return $xml;
	}
	
	private function filter_xml_str($str){
		return is_numeric($str) ? $str : '<![CDATA['.preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/", '', $str).']]>';
	}
	
	private function xml_body($arr){
		$xml = '';
		foreach($arr as $key => $val){
			is_numeric($key) && $key = "item id=\"$key\"";
			$xml .= "<$key>";
			$xml .= (is_array($val) || is_object($val)) ? $this->xml_body($val) : $this->filter_xml_str($val);
			list($key, ) = explode(' ', $key);
			$xml .= "</$key>";
		}
		return $xml;
	}
	
	public function xml_to_array($xml){
		if(!$xml){
			return array();
		}
        libxml_disable_entity_loader(true);
        $return = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
		return $return;
    }
	
}